/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../macro/head.h"
#include "include_odbc.h"
#include "odbc_stmt.h"
#include "mgr.h"

namespace xos_odbc
{
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static odbc_stmt::ITEM_DATA xos_item_data;

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    odbc_stmt::odbc_stmt()
    {
        init_data();
    }

    odbc_stmt::~odbc_stmt()
    {
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //  public method

    int odbc_stmt::get_xos_item_data( ITEM_DATA*& item_ptr )
    {
        int ret = 0;
        xos_item_data.set_container( mgr::container() );
        item_ptr = &xos_item_data;
        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // 绑定输出参数
    // 
    int odbc_stmt::bind_colum( int nCol, enumValueType eType, void * pBufByte, int nBufSize, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN * lpLenOrPtr = (SQLLEN *)StrLen_or_IndPtr;
        *lpLenOrPtr = 0;
        int nType = eType;

        if( ( 0 == ret ) && ( SQL_NULL_HSTMT == m_hStmt ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            to_len_or_ptr( *lpLenOrPtr, lpLenOrPtr );
            to_c_type( nType, &nType );
        }

        if( 0 == ret )
        {
            SQLRETURN r = SQLBindCol( m_hStmt, nCol + 1, nType, pBufByte, nBufSize, lpLenOrPtr );
            ret = m_err.stmt_ret( m_hStmt, r );
        }

        return ret;
    }

    // 
    // 绑定输入参数
    // 
    int odbc_stmt::bind_param( int nCol, enumDirection eType, enumValueType eValueType, 
        enumValueType eParamType, int ColSize,
        int DecimalDigits,
        void * ParamValuePtr,
        int BufLen,
        intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN * lpLenOrPtr = ( SQLLEN * )StrLen_or_IndPtr;
        int ValueType = eValueType;
        int ParamType = eParamType;
        int nType = eType;

        if( ( 0 == ret ) && ( SQL_NULL_HSTMT == m_hStmt ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            to_len_or_ptr( *lpLenOrPtr, lpLenOrPtr );
            to_sql_io_type( nType, &nType );
            to_c_type( ValueType, &ValueType );
            to_c_type( ParamType, &ParamType );
        }

        if( 0 == ret )
        {
            SQLRETURN r = SQLBindParameter( m_hStmt, nCol + 1, nType, ValueType, ParamType, ColSize, DecimalDigits, ParamValuePtr, BufLen, lpLenOrPtr );
            ret = m_err.stmt_ret( m_hStmt, r );
        }

        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // 绑定输入参数
    // 
    int odbc_stmt::bind_param( int nCol, const wchar_t * lpszData, int nNoop, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        nNoop = 0;

        SQLLEN * lpLenOrPtr = ( SQLLEN * )StrLen_or_IndPtr;
        *lpLenOrPtr = SQL_NTS;
        int ColSize = mgr::container()->crt()->strlen( lpszData ) * sizeof( wchar_t );
        int BufLen = ColSize + sizeof( wchar_t );
        int DecimalDigits = 0;
        void * ParamValuePtr = ( void * )lpszData;

        if( 0 == ret )
        {
            ret = bind_param( nCol, DIRECT_INPUT, VT_CHAR_ARRAY, VT_CHAR_ARRAY, ColSize, DecimalDigits, ParamValuePtr, BufLen, StrLen_or_IndPtr );
        }

        return ret;
    }

    // 
    // 绑定输入参数
    // 
    int odbc_stmt::bind_param( int nCol, int64_t * lpnData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN * lpLenOrPtr = ( SQLLEN * )StrLen_or_IndPtr;
        *lpLenOrPtr = sizeof( int64_t );
        int ColSize = sizeof( int64_t );
        int BufLen = ColSize;
        int DecimalDigits = 0;
        void * ParamValuePtr = ( void * )lpnData;

        if( 0 == ret )
        {
            ret = bind_param( nCol, DIRECT_INPUT, VT_I64, VT_I64, ColSize, DecimalDigits, ParamValuePtr, BufLen, StrLen_or_IndPtr );
        }

        return ret;
    }

    // 
    // 绑定输入参数
    // 
    int odbc_stmt::bind_param( int nCol, int32_t * lpnData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN * lpLenOrPtr = ( SQLLEN * )StrLen_or_IndPtr;
        *lpLenOrPtr = sizeof( int32_t );
        int ColSize = sizeof( int32_t );
        int BufLen = ColSize;
        int DecimalDigits = 0;
        void * ParamValuePtr = ( void * )lpnData;

        if( 0 == ret )
        {
            ret = bind_param( nCol, DIRECT_INPUT, VT_I32, VT_I32, ColSize, DecimalDigits, ParamValuePtr, BufLen, StrLen_or_IndPtr );
        }

        return ret;
    }

    // 
    // 绑定输入参数
    // 
    int odbc_stmt::bind_param( int nCol, int16_t * lpnData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN * lpLenOrPtr = ( SQLLEN * )StrLen_or_IndPtr;
        *lpLenOrPtr = sizeof( int16_t );
        int ColSize = sizeof( int16_t );
        int BufLen = ColSize;
        int DecimalDigits = 0;
        void * ParamValuePtr = ( void * )lpnData;

        if( 0 == ret )
        {
            ret = bind_param( nCol, DIRECT_INPUT, VT_I16, VT_I16, ColSize, DecimalDigits, ParamValuePtr, BufLen, StrLen_or_IndPtr );
        }

        return ret;
    }

    // 
    // 绑定输入参数
    // 
    int odbc_stmt::bind_param( int nCol, int8_t * lpnData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN * lpLenOrPtr = ( SQLLEN * )StrLen_or_IndPtr;
        *lpLenOrPtr = sizeof( int8_t );
        int ColSize = sizeof( int8_t );
        int BufLen = ColSize;
        int DecimalDigits = 0;
        void * ParamValuePtr = ( void * )lpnData;

        if( 0 == ret )
        {
            ret = bind_param( nCol, DIRECT_INPUT, VT_I8, VT_I8, ColSize, DecimalDigits, ParamValuePtr, BufLen, StrLen_or_IndPtr );
        }

        return ret;
    }

    // 
    // 绑定输入参数
    // 
    int odbc_stmt::bind_param( int nCol, uint64_t * lpnData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN * lpLenOrPtr = ( SQLLEN * )StrLen_or_IndPtr;
        *lpLenOrPtr = sizeof( uint64_t );
        int ColSize = sizeof( uint64_t );
        int BufLen = ColSize;
        int DecimalDigits = 0;
        void * ParamValuePtr = ( void * )lpnData;

        if( 0 == ret )
        {
            ret = bind_param( nCol, DIRECT_INPUT, VT_U64, VT_U64, ColSize, DecimalDigits, ParamValuePtr, BufLen, StrLen_or_IndPtr );
        }

        return ret;
    }

    // 
    // 绑定输入参数
    // 
    int odbc_stmt::bind_param( int nCol, uint32_t * lpnData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN * lpLenOrPtr = ( SQLLEN * )StrLen_or_IndPtr;
        *lpLenOrPtr = sizeof( uint32_t );
        int ColSize = sizeof( uint32_t );
        int BufLen = ColSize;
        int DecimalDigits = 0;
        void * ParamValuePtr = ( void * )lpnData;

        if( 0 == ret )
        {
            ret = bind_param( nCol, DIRECT_INPUT, VT_U32, VT_U32, ColSize, DecimalDigits, ParamValuePtr, BufLen, StrLen_or_IndPtr );
        }

        return ret;
    }

    // 
    // 绑定输入参数
    // 
    int odbc_stmt::bind_param( int nCol, uint16_t * lpnData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN * lpLenOrPtr = ( SQLLEN * )StrLen_or_IndPtr;
        *lpLenOrPtr = sizeof( uint16_t );
        int ColSize = sizeof( uint16_t );
        int BufLen = ColSize;
        int DecimalDigits = 0;
        void * ParamValuePtr = ( void * )lpnData;

        if( 0 == ret )
        {
            ret = bind_param( nCol, DIRECT_INPUT, VT_U16, VT_U16, ColSize, DecimalDigits, ParamValuePtr, BufLen, StrLen_or_IndPtr );
        }

        return ret;
    }

    // 
    // 绑定输入参数
    // 
    int odbc_stmt::bind_param( int nCol, uint8_t * lpnData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN * lpLenOrPtr = ( SQLLEN * )StrLen_or_IndPtr;
        *lpLenOrPtr = sizeof( uint8_t );
        int ColSize = sizeof( uint8_t );
        int BufLen = ColSize;
        int DecimalDigits = 0;
        void * ParamValuePtr = ( void * )lpnData;

        if( 0 == ret )
        {
            ret = bind_param( nCol, DIRECT_INPUT, VT_U8, VT_U8, ColSize, DecimalDigits, ParamValuePtr, BufLen, StrLen_or_IndPtr );
        }

        return ret;
    }

    // 
    // 绑定输入参数
    // 
    int odbc_stmt::bind_param( int nCol, bool * lpnData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN * lpLenOrPtr = ( SQLLEN * )StrLen_or_IndPtr;
        *lpLenOrPtr = sizeof( bool );
        int ColSize = sizeof( bool );
        int BufLen = ColSize;
        int DecimalDigits = 0;
        void * ParamValuePtr = ( void * )lpnData;

        if( 0 == ret )
        {
            ret = bind_param( nCol, DIRECT_INPUT, VT_BOOL, VT_BOOL, ColSize, DecimalDigits, ParamValuePtr, BufLen, StrLen_or_IndPtr );
        }

        return ret;
    }

    // 
    // 绑定输入参数
    // 
    int odbc_stmt::bind_param( int nCol, float * lpfData, int nDigitNum, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN * lpLenOrPtr = ( SQLLEN * )StrLen_or_IndPtr;
        *lpLenOrPtr = sizeof( float );
        int ColSize = sizeof( float );
        int BufLen = ColSize;
        int DecimalDigits = 0;
        void * ParamValuePtr = ( void * )lpfData;

        if( 0 == ret )
        {
            ret = bind_param( nCol, DIRECT_INPUT, VT_FLOAT, VT_FLOAT, ColSize, DecimalDigits, ParamValuePtr, BufLen, StrLen_or_IndPtr );
        }

        return ret;
    }

    // 
    // 绑定输入参数
    // 
    int odbc_stmt::bind_param( int nCol, double * lpdData, int nDigitNum, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN * lpLenOrPtr = ( SQLLEN * )StrLen_or_IndPtr;
        *lpLenOrPtr = sizeof( double );
        int ColSize = sizeof( double );
        int BufLen = ColSize;
        int DecimalDigits = 0;
        void * ParamValuePtr = ( void * )lpdData;

        if( 0 == ret )
        {
            ret = bind_param( nCol, DIRECT_INPUT, VT_DOUBLE, VT_DOUBLE, ColSize, DecimalDigits, ParamValuePtr, BufLen, StrLen_or_IndPtr );
        }

        return ret;
    }

    // 
    // 绑定输出参数
    // 
    int odbc_stmt::bind_colum( int nCol, wchar_t * lpData, int nBufSize, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;
        ret = bind_colum( nCol, VT_CHAR_ARRAY, lpData, nBufSize, StrLen_or_IndPtr );
        return ret;
    }

    // 
    // 绑定输出参数
    // 
    int odbc_stmt::bind_colum( int nCol, int64_t * lpData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;
        ret = bind_colum( nCol, VT_I64, lpData, sizeof( int64_t ), StrLen_or_IndPtr );
        return ret;
    }

    // 
    // 绑定输出参数
    // 
    int odbc_stmt::bind_colum( int nCol, int32_t * lpData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;
        ret = bind_colum( nCol, VT_I32, lpData, sizeof( int32_t ), StrLen_or_IndPtr );
        return ret;
    }

    // 
    // 绑定输出参数
    // 
    int odbc_stmt::bind_colum( int nCol, int16_t * lpData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;
        ret = bind_colum( nCol, VT_I16, lpData, sizeof( int16_t ), StrLen_or_IndPtr );
        return ret;
    }

    // 
    // 绑定输出参数
    // 
    int odbc_stmt::bind_colum( int nCol, int8_t * lpData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;
        ret = bind_colum( nCol, VT_I8, lpData, sizeof( int8_t ), StrLen_or_IndPtr );
        return ret;
    }

    // 
    // 绑定输出参数
    // 
    int odbc_stmt::bind_colum( int nCol, uint64_t * lpData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;
        ret = bind_colum( nCol, VT_U64, lpData, sizeof( uint64_t ), StrLen_or_IndPtr );
        return ret;
    }

    // 
    // 绑定输出参数
    // 
    int odbc_stmt::bind_colum( int nCol, uint32_t * lpData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;
        ret = bind_colum( nCol, VT_U32, lpData, sizeof( uint32_t ), StrLen_or_IndPtr );
        return ret;
    }

    // 
    // 绑定输出参数
    // 
    int odbc_stmt::bind_colum( int nCol, uint16_t * lpData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;
        ret = bind_colum( nCol, VT_U16, lpData, sizeof( uint16_t ), StrLen_or_IndPtr );
        return ret;
    }

    // 
    // 绑定输出参数
    // 
    int odbc_stmt::bind_colum( int nCol, uint8_t * lpData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;
        ret = bind_colum( nCol, VT_U8, lpData, sizeof( uint8_t ), StrLen_or_IndPtr );
        return ret;
    }

    // 
    // 绑定输出参数
    // 
    int odbc_stmt::bind_colum( int nCol, bool * lpData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;
        ret = bind_colum( nCol, VT_BOOL, lpData, sizeof( bool ), StrLen_or_IndPtr );
        return ret;
    }

    // 
    // 绑定输出参数
    // 
    int odbc_stmt::bind_colum( int nCol, float * lpData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;
        ret = bind_colum( nCol, VT_FLOAT, lpData, sizeof( float ), StrLen_or_IndPtr );
        return ret;
    }

    // 
    // 绑定输出参数
    // 
    int odbc_stmt::bind_colum( int nCol, double * lpData, intptr_t * StrLen_or_IndPtr )
    {
        int ret = 0;
        ret = bind_colum( nCol, VT_DOUBLE, lpData, sizeof( double ), StrLen_or_IndPtr );
        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // 查询结果集中的列数,index从0开始
    //
    int odbc_stmt::get_col_info( int nIndex, char * lpszName, int nLen, int & nType, int & nSize, int & nDigitNum, int & nCanNull )
    {
        int ret = 0;

        xos_box::i_string * pStrA = mgr::container()->box()->string();
        xos_box::i_buf * pBuf = mgr::container()->box()->buf();

        SQLSMALLINT name_len = (SQLSMALLINT)( pBuf->get_buf_size( 0 ) / sizeof( wchar_t ) );
        SQLWCHAR * lpszwName = (SQLWCHAR *)pBuf->get_data( 0, 0, 0, 0 );
        SQLSMALLINT data_type = 0;
        SQLSMALLINT nLenNeed = 0;
#if defined( _MSC_VER ) || defined( XOS_MAC ) || defined( XOS_IOS_STATIC ) || defined( XOS_IOS_SIMULATOR ) || defined(XOS_LINUX) || defined(XOS_ANDROID)
        SQLULEN col_size = 0;
#else
        SQLUINTEGER col_size = 0;
#endif
        SQLSMALLINT digit_num = 0;
        SQLSMALLINT can_null = 0;

        if( ( 0 == ret ) && ( SQL_NULL_HSTMT == m_hStmt ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            SQLRETURN r = SQLDescribeColW( m_hStmt, nIndex + 1, lpszwName, name_len, &nLenNeed, &data_type, &col_size, &digit_num, &can_null );
            ret = m_err.stmt_ret( m_hStmt, r );
        }

        if( 0 == ret )
        {
            pBuf->set_len( nLenNeed * sizeof( int16_t ) );
            mgr::container()->misc()->utf16_to_utf8( pBuf, pStrA );
            mgr::container()->crt()->strncpy( lpszName, nLen, pStrA->get( 0, 0 ), pStrA->length() );
            nDigitNum = (int)digit_num;
            nCanNull = (int)can_null;
            nType = (int)data_type;
            nSize = (int)col_size;
            from_sql_type( nType, &nType );
        }

        xos_stl::release_interface( pStrA );
        xos_stl::release_interface( pBuf );

        return ret;
    }

    // 
    // 执行DML后，影响的行数
    // 
    int odbc_stmt::get_affect_row_num( int & nNum )
    {
        int ret = 0;

        SQLLEN nRowNum = 0;

        if( ( 0 == ret ) && ( SQL_NULL_HSTMT == m_hStmt ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            SQLRETURN r = SQLRowCount( m_hStmt, &nRowNum );
            if( SQL_SUCCESS != r )
            {
                m_err.get_info( SQL_HANDLE_STMT, m_hStmt );
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            nNum = (int)nRowNum;
        }

        return ret;
    }

    // 
    // 得到结果集行数
    // 
    int odbc_stmt::get_row_num( int & nNum )
    {
        int ret = 0;

        SQLLEN nRowNum = 0;

        if( ( 0 == ret ) && ( SQL_NULL_HSTMT == m_hStmt ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            SQLRETURN r = SQLFetchScroll( m_hStmt, SQL_FETCH_LAST, 0 );
            if( SQL_SUCCESS != r )
            {
                m_err.get_info( SQL_HANDLE_STMT, m_hStmt );
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            SQLINTEGER nRetLen = 0;
            SQLRETURN r = SQLGetStmtAttrW( m_hStmt, SQL_ATTR_ROW_NUMBER, (SQLPOINTER)&nRowNum, SQL_IS_INTEGER, &nRetLen );
            if( SQL_SUCCESS != r )
            {
                m_err.get_info( SQL_HANDLE_STMT, m_hStmt );
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            SQLRETURN r = SQLFetchScroll( m_hStmt, SQL_FETCH_FIRST, 0 );
            if( SQL_SUCCESS != r )
            {
                m_err.get_info( SQL_HANDLE_STMT, m_hStmt );
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            nNum = (int)nRowNum;
        }

        return ret;
    }

    // 
    // 查询结果集中的列数
    // 
    int odbc_stmt::get_col_num( int & nNum )
    {
        int ret = 0;

        SQLSMALLINT num = 0;

        if( ( 0 == ret ) && ( SQL_NULL_HSTMT == m_hStmt ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            SQLRETURN r = SQLNumResultCols( m_hStmt, &num );
            if( SQL_SUCCESS != r )
            {
                m_err.get_info( SQL_HANDLE_STMT, m_hStmt );
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            nNum = (int)num;
        }

        return ret;
    }

    // 
    // 直接运行sql
    // 
    //  0 : success. 
    //  1 : running. 
    // -1 : failed
    // 
    int odbc_stmt::execute_direct( const char * lpszSql )
    {
        xos_box::i_string * pStrA = mgr::container()->box()->string();
        xos_box::i_buf * pBuf = mgr::container()->box()->buf();
        SQLRETURN sqlRet = SQL_SUCCESS;
        int ret = 0;

        if( ( 0 == ret ) && ( SQL_NULL_HSTMT == m_hStmt ) )
        {
            ret = -1;
        }

        if( 0 == ret )
        {
            pStrA->set( lpszSql );
            mgr::container()->misc()->utf8_to_utf16( pStrA, pBuf );
        }

        if( 0 == ret )
        {
            sqlRet = SQLExecDirectW( m_hStmt, (SQLWCHAR *)pBuf->get_data( 0, 0, 0, 0 ), SQL_NTS );
            ret = m_err.stmt_ret( m_hStmt, sqlRet );
        }

        xos_stl::release_interface( pBuf );
        xos_stl::release_interface( pStrA );

        return ret;
    }

    //
    // 编译sql
    // 
    //  0 : success. 
    //  1 : running. 
    // -1 : failed
    // 
    int odbc_stmt::compile_sql( const char * lpszSql )
    {
        xos_box::i_string * pStrA = mgr::container()->box()->string();
        xos_box::i_buf * pBuf = mgr::container()->box()->buf();
        SQLRETURN sqlRet = SQL_SUCCESS;
        int ret = 0;

        if( lpszSql )
        {
            pStrA->set( lpszSql );
            mgr::container()->misc()->utf8_to_utf16( pStrA, pBuf );
            m_sql = lpszSql;
        }
        {
            sqlRet = SQLPrepareW( m_hStmt, (SQLWCHAR *)pBuf->get_data( 0, 0, 0, 0 ), SQL_NTS );
            ret = m_err.stmt_ret( m_hStmt, sqlRet );
        }

        xos_stl::release_interface( pStrA );
        xos_stl::release_interface( pBuf );

        return ret;
    }

    // 
    // 绑定输入后执行sql语句写入
    // 
    //  0 : success. 
    //  1 : running. 
    // -1 : failed
    // 
    int odbc_stmt::execute()
    {
        SQLRETURN sqlRet = SQL_SUCCESS;
        int ret = 0;

        if( ( 0 == ret ) && ( SQL_NULL_HSTMT == m_hStmt ) )
        {
            ret = -1;
        }

        if( 0 == ret )
        {
            sqlRet = SQLExecute( m_hStmt );
            ret = m_err.stmt_ret( m_hStmt, sqlRet );
        }

        return ret;
    }

    // 
    //  0 : success
    //  1 : pending
    //  2 : no data
    // -1 : failed
    // 
    int odbc_stmt::fetch()
    {
        int ret = 0;

        if( ( 0 == ret ) && ( SQL_NULL_HSTMT == m_hStmt ) )
        {
            ret = -1;
        }

        if( 0 == ret )
        {
            SQLRETURN sqlRet = SQLFetch( m_hStmt );
            ret = m_err.stmt_ret( m_hStmt, sqlRet );
        }

        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // 翻译一下odbc返回的StrLen_or_IndPtr为i_stmt中的enumLenOrPtr类型
    // 
    int odbc_stmt::translate_strlen_or_indptr( intptr_t StrLen_or_IndPtr, intptr_t * lp_StrLen_or_IndPtr )
    {
        int ret = 0;

        SQLLEN LenOrPtr = (SQLLEN)StrLen_or_IndPtr;

        if( 0 == ret )
        {
            ret = from_len_or_ptr( LenOrPtr, &LenOrPtr );
        }

        if( ( 0 == ret ) && lp_StrLen_or_IndPtr )
        {
            *lp_StrLen_or_IndPtr = LenOrPtr;
        }

        return ret;
    }

    int odbc_stmt::from_len_or_ptr( SQLLEN LenOrPtr, SQLLEN * lpLenOrPtr )
    {
        SQLLEN result = LenOrPtr;
        bool bTranslate = true;
        int ret = 0;

        switch( LenOrPtr )
        {
        case SQL_DEFAULT_PARAM:
            {
                result = LP_DEFAULT_PARAM;
            }
            break;
        case SQL_DATA_AT_EXEC:
            {
                result = LP_DATA_AT_EXEC;
            }
            break;
        case SQL_NULL_DATA:
            {
                result = LP_NULL_DATA;
            }
            break;
        case SQL_NTS:
            {
                result = LP_NTS;
            }
            break;
        default:
            {
                bTranslate = false;
            }
            break;
        }

        if( ( 0 == ret ) && bTranslate && lpLenOrPtr )
        {
            *lpLenOrPtr = result;
        }

        return ret;
    }

    int odbc_stmt::to_len_or_ptr( SQLLEN LenOrPtr, SQLLEN * lpLenOrPtr )
    {
        SQLLEN result = LenOrPtr;
        bool bTranslate = true;
        int ret = 0;

        switch( LenOrPtr )
        {
        case LP_DEFAULT_PARAM:
            {
                result = SQL_DEFAULT_PARAM;
            }
            break;
        case LP_DATA_AT_EXEC:
            {
                result = SQL_DATA_AT_EXEC;
            }
            break;
        case LP_NULL_DATA:
            {
                result = SQL_NULL_DATA;
            }
            break;
        case LP_NTS:
            {
                result = SQL_NTS;
            }
            break;
        default:
            {
                bTranslate = false;
            }
            break;
        }

        if( ( 0 == ret ) && bTranslate && lpLenOrPtr )
        {
            *lpLenOrPtr = result;
        }

        return ret;
    }

    int odbc_stmt::to_sql_io_type( int nInputType, int * lpnOutType )
    {
        int result = 0;
        int ret = 0;

        switch( nInputType )
        {
        case DIRECT_INPUT_OUTPUT:
            {
                result = SQL_PARAM_INPUT_OUTPUT;
            }
            break;
        case DIRECT_OUTPUT:
            {
                result = SQL_PARAM_OUTPUT;
            }
            break;
        case DIRECT_INPUT:
            {
                result = SQL_PARAM_INPUT;
            }
            break;
        default:
            {
                ret = 1;
            }
            break;
        }

        if( ( 0 == ret ) && lpnOutType )
        {
            *lpnOutType = result;
        }

        return ret;
    }

    int odbc_stmt::from_sql_type( int nInputType, int * lpnOutType )
    {
        using namespace std;
        int result = 0;
        int ret = 0;

        switch( nInputType )
        {
        case SQL_LONGVARCHAR:
        case SQL_VARCHAR:
            {
                cout << "nInputType = " << nInputType << endl;
                assert( false );
                result = VT_CHAR_ARRAY;
            }
            break;
        case SQL_TYPE_TIMESTAMP:
        case SQL_TIMESTAMP:
        case SQL_WLONGVARCHAR:
        case SQL_WVARCHAR:
        case SQL_WCHAR:
            {
                result = VT_CHAR_ARRAY;
            }
            break;
        case SQL_DOUBLE:
            {
                result = VT_DOUBLE;
            }
            break;
        case SQL_REAL:
            {
                result = VT_FLOAT;
            }
            break;
        case SQL_SMALLINT:
            {
                result = VT_I16;
            }
            break;
        case SQL_INTEGER:
            {
                result = VT_I32;
            }
            break;
        case SQL_BIGINT:
            {
                result = VT_I64;
            }
            break;
        default:
            {
                cout << "nInputType = " << nInputType << endl;
                assert( false );
                ret = 1;
            }
            break;
        }

        if( ( 0 == ret ) && lpnOutType )
        {
            *lpnOutType = result;
        }

        return ret;
    }

    int odbc_stmt::to_c_type( int nInputType, int * lpnOutType )
    {
        int result = 0;
        int ret = 0;

        switch( nInputType )
        {
        case VT_CHAR_ARRAY:
            {
                result = SQL_C_WCHAR;
            }
            break;
        case VT_U16:
            {
                result = SQL_C_USHORT;
            }
            break;
        case VT_I16:
            {
                result = SQL_C_SSHORT;
            }
            break;
        case VT_U32:
            {
                result = SQL_C_ULONG;
            }
            break;
        case VT_I32:
            {
                result = SQL_C_SLONG;
            }
            break;
        case VT_U64:
            {
                result = SQL_C_UBIGINT;
            }
            break;
        case VT_I64:
            {
                result = SQL_C_SBIGINT;
            }
            break;
        case VT_FLOAT:
            {
                result = SQL_C_FLOAT;
            }
            break;
        case VT_DOUBLE:
            {
                result = SQL_C_DOUBLE;
            }
            break;
        case VT_I8:
            {
                result = SQL_C_STINYINT;
            }
            break;
        case VT_U8:
            {
                result = SQL_C_TINYINT;
            }
            break;
        case VT_BOOL:
            {
                result = SQL_C_BIT;
            }
            break;
        case VT_BIN:
            {
                result = SQL_C_BINARY;
            }
            break;
        default:
            {
                ret = 1;
            }
            break;
        }

        if( ( 0 == ret ) && lpnOutType )
        {
            *lpnOutType = result;
        }

        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int odbc_stmt::set_handle( SQLHANDLE hStmt )
    {
        int ret = 0;
        m_hStmt = hStmt;
        return ret;
    }

    SQLHANDLE odbc_stmt::handle() const
    {
        return m_hStmt;
    }

    int odbc_stmt::init()
    {
        int ret = 0;
        return ret;
    }

    int odbc_stmt::term()
    {
        int ret = 0;

        if( SQL_NULL_HSTMT != m_hStmt )
        {
            SQLCloseCursor( m_hStmt );
            SQLFreeHandle( SQL_HANDLE_STMT, m_hStmt );
            m_hStmt = SQL_NULL_HSTMT;
        }

        init_data();

        return ret;
    }

    int odbc_stmt::init_data()
    {
        int ret = 0;
        m_hStmt = SQL_NULL_HSTMT;
        m_sql = "";
        m_err.clear();
        return ret;
    }

} // xos_odbc
